package com.example.demo.utils;

import org.apache.commons.beanutils.Converter;
import org.apache.commons.lang.StringUtils;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;


public class CommonConvert implements Converter {

    public static final String JAVA_SQL_TIMESTAMP = "java.sql.Timestamp";
    public static final String JAVA_LANG_STRING = "java.lang.String";
    public static final String JAVA_LANG_FLOAT = "java.lang.Float";
    public static final String JAVA_LANG_LONG = "java.lang.Long";
    public static final String JAVA_LANG_INTEGER = "java.lang.Integer";
    public static final String JAVA_MATH_BIG_DECIMAL = "java.math.BigDecimal";
    public static final String JAVA_LANG_BOOLEAN = "java.lang.Boolean";
    public static final String JAVAX_XML_DATATYPE_XMLGREGORIAN_CALENDAR = "javax.xml.datatype.XMLGregorianCalendar";
    public static final String BOOLEAN_TRUE = "true";
    public static final String DIGIT_ONE = "1";

    @Override
    public <T> T convert(Class<T> aClass, Object value) {
        try {
            if (value == null) {
                return null;
            }
            if (value instanceof Timestamp && JAVA_SQL_TIMESTAMP.equalsIgnoreCase(aClass.getName())) {
                return (T) value;
            }
            if (value instanceof String && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                return (T) value;
            }
            if (value instanceof String && JAVA_SQL_TIMESTAMP.equalsIgnoreCase(aClass.getName())) {
                String dateStr = (String) value;
                if (StringUtils.isEmpty(dateStr))
                    return null;
                Timestamp endTime;
                String regexp1 = "([0-9]{4})-([0-1][0-9])-([0-3][0-9])T([0-2][0-9]):([0-6][0-9]):([0-6][0-9])";
                String regexp2 = "([0-9]{4})-([0-1][0-9])-([0-3][0-9]) ([0-2][0-9]):([0-6][0-9]):([0-6][0-9])";
                String regexp3 = "([0-9]{4})-(0?[0-9]|1[0-2])-(0?[0-9]|[0-3][0-9])";
                if (dateStr.matches(regexp1)) {
                    dateStr = dateStr.split("T")[0] + " " + dateStr.split("T")[1];
                    endTime = Timestamp.valueOf(dateStr);
                    return (T) endTime;
                } else if (dateStr.matches(regexp2)) {
                    endTime = Timestamp.valueOf(dateStr);
                    return (T) endTime;
                } else if (dateStr.matches(regexp3)) {
                    dateStr = dateStr + " 00:00:00";
                    endTime = Timestamp.valueOf(dateStr);
                    return (T) endTime;
                } else {
                    return (T) Timestamp.valueOf(dateStr);
                }
            }
            if (value instanceof Timestamp && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                String dateStr;
                Timestamp endTime = (Timestamp) value;
                DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                dateStr = sdf.format(endTime);
                return (T) dateStr;
            }

            if (value instanceof java.sql.Date && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                java.sql.Date value2 = (java.sql.Date) value;
                return (T) value2.toLocalDate().toString();
            }

            if (value instanceof Float && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {

                return (T) value.toString();
            }
            if (value instanceof String && JAVA_LANG_FLOAT.equalsIgnoreCase(aClass.getName())) {
                if (StringUtils.isEmpty(value.toString())) {
                    value = "0";
                }
                return (T) (Float) Float.parseFloat(value.toString());
            }
            if (value instanceof Long && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                return (T) value.toString();
            }
            if (value instanceof String && JAVA_LANG_LONG.equalsIgnoreCase(aClass.getName())) {
                if (StringUtils.isEmpty(value.toString())) {
                    value = "0";
                }
                return (T) (Long) Long.parseLong(value.toString());
            }
            if (value instanceof Integer && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                return (T) value.toString();
            }
            if (value instanceof String && JAVA_LANG_INTEGER.equalsIgnoreCase(aClass.getName())) {
                if (StringUtils.isEmpty(value.toString())) {
                    value = "0";
                }
                return (T) (Integer) Integer.parseInt(value.toString());
            }
            if (value instanceof BigDecimal && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                return (T) value.toString();
            }
            if (value instanceof String && JAVA_MATH_BIG_DECIMAL.equalsIgnoreCase(aClass.getName())) {
                if (StringUtils.isEmpty(value.toString())) {
                    value = "0";
                }
                return (T) new BigDecimal(value.toString());
            }
            if (value instanceof Boolean && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                if (((Boolean) value).booleanValue()) {
                    return (T) "1";
                } else {
                    return (T) "0";
                }
            }
            if (value instanceof String && JAVA_LANG_BOOLEAN.equalsIgnoreCase(aClass.getName())) {
                if (DIGIT_ONE.equalsIgnoreCase(value.toString()) || BOOLEAN_TRUE.equalsIgnoreCase(value.toString())) {
                    return (T) Boolean.TRUE;
                } else {
                    return (T) Boolean.FALSE;
                }
            }
            //从XMLGregorianCalendar转换成Timestamp
            if (value instanceof XMLGregorianCalendar && JAVA_SQL_TIMESTAMP.equalsIgnoreCase(aClass.getName())) {
                XMLGregorianCalendar calendarValue = (XMLGregorianCalendar) value;
                Timestamp timestamp = new Timestamp(calendarValue.toGregorianCalendar().getTimeInMillis());
                return (T) timestamp;
            }
            //从Timestamp转换成XMLGregorianCalendar
            if (value instanceof Timestamp && JAVAX_XML_DATATYPE_XMLGREGORIAN_CALENDAR.equalsIgnoreCase(aClass.getName())) {
                GregorianCalendar gc = new GregorianCalendar();
                Timestamp timestampValue = (Timestamp) value;
                gc.setTime(new Date(timestampValue.getTime()));
                XMLGregorianCalendar cal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
                return (T) cal;
            }
            //String to Collection
            if (value instanceof String && Collection.class.isAssignableFrom(aClass)) {

                if (aClass.isAssignableFrom(List.class)) {
                    List<String> list = new ArrayList<>();
                    String[] split = value.toString().split(",");
                    for (String str : split) {
                        list.add(str);
                    }
                    return (T) list;
                }
                if (aClass.isAssignableFrom(Set.class)) {
                    Set<String> set = new HashSet<>();
                    String[] split = value.toString().split(",");
                    for (String str : split) {
                        set.add(str);
                    }
                    return (T) set;
                }
            }

            //Collection to String
            if (Collection.class.isAssignableFrom(value.getClass()) && JAVA_LANG_STRING.equalsIgnoreCase(aClass.getName())) {
                return (T) StringUtils.join((Collection) value, ",");
            }
        } catch (Exception e) {
            //throw new Exception("BeanUtilEx Convert Error", e.getMessage());
        }
        return (T) value;
    }
}
